package com.bluedon.ism.commons.util;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * 加密工具类
 */
public class CipherUtil {

    private static final String KEY_ALGORITHM = "RSA";    
    public static final String PUBLIC_KEY ="publicKey";  
    public static final String PRIVATE_KEY ="privateKey";  
    public static Map<String, String> keyMap;
    
    static {
            genKey(true);
    }
    
    /**
     * 32bit LowerCase MD5 encode
     * @param 待加密的字符串
     * @return
     */
    public static String MD5Encode(String origin) {
        return DigestUtils.md5Hex(origin); 
    }
    
    public static void main(String[] args) throws Exception, InvalidKeySpecException, IOException, Exception {
        String str3des ="XctFDyNbhy3UPEd3OKxc7y/uegtj8OQXg0JUEpjdXKz05faL7hlBwBqv1SsqVeebx3b89sPrB6/9" +
                "SiUGlLNDxUpVWri5xl5Z42p2qit15F9891N/QCyz4UpepegKg4fMc6bvCVWpHCCrc4a/1/7p/Ttu" +
                "AKPqU2iJacIvdCc+A+8=";
      String source = "测试";
      String encodeStr = encoderstr(source, CipherUtil.createRSAPublicKey(keyMap.get(PUBLIC_KEY)));
      System.out.println(encodeStr);
      System.out.println(decoderstr(encodeStr, CipherUtil.createRSAPrivateKey(keyMap.get(PRIVATE_KEY))));
      System.out.println(MD5Encode("123456"));
      System.out.println(MD5Encode(MD5Encode("123456")));
    }
    
    public static Map<String,String> genKey() {
        return genKey(false);
    }
    public static Map<String,String> genKey(boolean createNew) {
        if (!createNew)
            return keyMap;
        keyMap = new HashMap<String,String>();
        KeyPairGenerator keygen = null;
        try {
            keygen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("create keygen error " + e);
        }
        SecureRandom random = new SecureRandom();
        // random.setSeed(keyInfo.getBytes());
        // 初始加密，512位已被破解，用1024位,最好用2048位
        keygen.initialize(1024, random);
        // 取得密钥对
        KeyPair kp = keygen.generateKeyPair();
        RSAPrivateKey privateKey = (RSAPrivateKey)kp.getPrivate();
        String privateKeyString = Base64.encodeBase64String(privateKey.getEncoded());
        
        RSAPublicKey publicKey = (RSAPublicKey)kp.getPublic(); 
        String publicKeyString = Base64.encodeBase64String(publicKey.getEncoded());
        keyMap.put(PUBLIC_KEY, publicKeyString);
        keyMap.put(PRIVATE_KEY, privateKeyString);
        return keyMap;
    }
    
    /**
     * 3des 解密
     * @param encodestr
     * @param privatekey
     * @return
     * @throws Exception
     */
    public static  String decoder3desstr(String encodestr, String str3des)  {
        if("".equals(encodestr)){
            return "";
        }
        try {
//            Security.addProvider(new com.sun.crypto.provider.SunJCE());
            Cipher cipher = Cipher.getInstance("DESede");
            SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.decodeBase64(str3des), "DESede");
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            // 根据公钥，对Cipher对象进行初始化
            byte[] resultBytes = cipher.doFinal(Base64.decodeBase64(encodestr));
            return new String(resultBytes, "UTF-8");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 3des 加密
     * @param encodestr
     * @param privatekey
     * @return
     * @throws Exception
     */
    public static  String encoder3desstr(String encodestr, String str3des) {
        try {
//            Security.addProvider(new com.sun.crypto.provider.SunJCE());
            Cipher cipher = Cipher.getInstance("DESede");
            SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.decodeBase64(str3des), "DESede");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            // 根据公钥，对Cipher对象进行初始化
            byte[] resultBytes = cipher.doFinal(encodestr.getBytes("UTF-8"));
            return Base64.encodeBase64String(resultBytes);
        }catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    /**
     * 3des 加密
     * @param encodestr
     * @param privatekey
     * @return
     * @throws Exception
     */
    public static  String encoder3desstr(String encodestr) {
        try {
//            Security.addProvider(new com.sun.crypto.provider.SunJCE());
            //KeyGenerator提供对称密钥生成器的功能，支持各种算法  
            KeyGenerator keygen;  
            //SecretKey负责保存对称密钥   
            SecretKey deskey;     
            //实例化支持3DES算法的密钥生成器，算法名称用DESede  
            keygen = KeyGenerator.getInstance("DESede");      
            //生成密钥  
            deskey = keygen.generateKey();  
            
            Cipher cipher = Cipher.getInstance("DESede");
            cipher.init(Cipher.ENCRYPT_MODE, deskey);
            // 根据公钥，对Cipher对象进行初始化
            byte[] resultBytes = cipher.doFinal(encodestr.getBytes("UTF-8"));
            return Base64.encodeBase64String(resultBytes);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 根据私钥解密
     * @author czw
     * @param encodestr
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static  String decoderstr(String encodestr, PrivateKey privateKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            // 根据公钥，对Cipher对象进行初始化
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] resultBytes = cipher.doFinal(Base64.decodeBase64(encodestr));
            return new String(resultBytes, "UTF-8");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 根据公钥加密
     * @author czw
     * @param encodestr
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static String encoderstr(String encodestr, PublicKey publicKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            // 根据公钥，对Cipher对象进行初始化
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] resultBytes = cipher.doFinal(encodestr.getBytes("UTF-8"));
            return Base64.encodeBase64String(resultBytes);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    
    public static PublicKey createRSAPublicKey(String strPublicKey)  {
        try {
            X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.decodeBase64(strPublicKey));  
            KeyFactory  keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(spec);
            return publicKey;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    
    public static PrivateKey createRSAPrivateKey(String strPrivateKey) {
        try {
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(strPrivateKey));
            KeyFactory  keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            return privateKey;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}
